<template>
  <a-card>
    <a-row class="mb-10" :gutter="24">
      <a-col :span="6">
        <a-input
          placeholder="请输入角色名称"
          v-model:value="state.searchInfo.roleName"
        />
      </a-col>
      <a-col>
        <a-button type="primary" class="mr-10" @click="handleSearch"
          >搜索</a-button
        >
        <a-button class="mr-10" @click="handleReset">重置</a-button>
      </a-col>
    </a-row>
    <a-row class="mb-10">
      <a-col>
        <a-button type="primary" @click="showModal()">新增</a-button>
      </a-col>
    </a-row>
    <a-table
      :columns="columns"
      :row-key="(record) => record.id"
      :data-source="state.dataSource"
      :pagination="state.pagination"
      :loading="state.loading"
      @change="handleTableChange"
    >
      <template #action="{ record }">
        <span>
          <a-button type="link" @click="() => showModal(record)">
            修改
          </a-button>
          <a-popconfirm title="确定删除?" @confirm="() => handleDelete(record)">
            <a-button
              :disabled="['admin'].includes(record.roleKey)"
              type="link"
            >
              删除
            </a-button>
          </a-popconfirm>
        </span>
      </template>
    </a-table>

    <a-modal
      v-model:visible="modalState.visible"
      :title="modalState.title"
      @ok="handleOk"
      @cancel="handleCancel"
    >
      <a-form
        ref="formRef"
        :model="formState"
        :rules="rules"
        :labelCol="{ style: { width: '100px' } }"
      >
        <a-form-item label="角色名称" name="roleName">
          <a-input v-model:value="formState.roleName" />
        </a-form-item>
        <a-form-item label="权限字符" name="roleKey">
          <a-input v-model:value="formState.roleKey" />
        </a-form-item>
        <a-form-item label="菜单权限" name="menus">
          <div class="mt-5 mb-10">
            <a-checkbox
              v-model:checked="treeState.expandAll"
              @change="handleExpandAll"
              >展开/折叠</a-checkbox
            >
            <a-checkbox
              v-model:checked="treeState.checkAll"
              @change="handleCheckAll"
              >全选/全不选</a-checkbox
            >
          </div>
          <div class="tree-box">
            <a-tree
              v-if="treeState.treeData.length"
              checkable
              :replaceFields="{
                key: 'path',
              }"
              :tree-data="treeState.treeData"
              v-model:expandedKeys="treeState.expandedKeys"
              v-model:checkedKeys="formState.checkedMenus"
            >
            </a-tree>
          </div>
        </a-form-item>
      </a-form>
    </a-modal>
  </a-card>
</template>

<script setup>
import { reactive, ref } from "@vue/reactivity";
import { getRoleList, addRole, updateRole, deleteRole } from "@/api/role";
import { getAllRoutes } from "@/api/routes";
import { computed, onBeforeMount } from "@vue/runtime-core";
import { treeToList } from "@/utils/treeHelper";
import { store } from "@/store/index";

function initTree(treeNode) {
  for (let i = 0; i < treeNode.length; i += 1) {
    let item = treeNode[i];
    const { path, meta = {} } = item;
    treeNode[i] = {
      ...item,
      ...meta,
      key: path,
    };
    if (item.children && item.children.length > 0) {
      initTree(item.children);
    }
  }
  return treeNode;
}

const columns = [
  {
    title: "角色名称",
    dataIndex: "roleName",
  },
  {
    title: "权限字符",
    dataIndex: "roleKey",
  },
  {
    title: "操作",
    dataIndex: "action",
    slots: { customRender: "action" },
  },
];

const getInitialSearch = () => ({
  pagination: {
    current: 1,
    pageSize: 10,
    total: 0,
    showSizeChanger: true,
    showTotal: (total) => `共${total}条`,
  },
  searchInfo: {
    roleName: "",
  },
});

const state = reactive({
  dataSource: [],
  ...getInitialSearch(),
  loading: false,
});

const init = () => {
  const { current, pageSize } = state.pagination;
  const params = {
    current,
    pageSize,
    ...state.searchInfo,
  };
  state.loading = true;
  // 获取角色列表
  getRoleList(params)
    .then((res) => {
      state.dataSource = res.data.list;
      state.pagination.total = res.data.total;
    })
    .finally(() => {
      state.loading = false;
    });
};

const handleSearch = () => {
  state.pagination.current = 1;
  init();
};

const handleReset = () => {
  Object.assign(state, getInitialSearch());
  init();
};

const handleTableChange = (pag, filters) => {
  state.pagination.current = pag.current;
  state.pagination.pageSize = pag.pageSize;
  state.searchInfo = {
    ...state.searchInfo,
    ...filters,
  };
  init();
};

const handleDelete = (record) => {
  deleteRole(record.id).then(() => {
    init();
  });
};

onBeforeMount(() => {
  init();
});

// 弹窗
const modalState = reactive({
  visible: false,
  title: "",
});
// 添加编辑表单
const formRef = ref();
const getInitialData = () => ({
  roleName: "",
  roleKey: "",
  checkedMenus: [],
});
const formState = reactive(getInitialData());
const rules = {
  roleName: [{ required: true, message: "请输入角色名", trigger: "blur" }],
  roleKey: [{ required: true, message: "请输入权限字符", trigger: "blur" }],
};
// 树形
const getInitialTree = () => ({
  expandAll: false,
  checkAll: false,
  treeData: [],
  expandedKeys: [],
});
const treeState = reactive(getInitialTree());
const treeKeys = computed(() => {
  const keys = treeToList(treeState.treeData).map((v) => v.path);
  return keys;
});
// 全部展开事件
const handleExpandAll = () => {
  if (treeState.expandAll) {
    treeState.expandedKeys = [...treeKeys.value];
  } else {
    treeState.expandedKeys = [];
  }
};
// 全选事件
const handleCheckAll = () => {
  if (treeState.checkAll) {
    formState.checkedMenus = [...treeKeys.value];
  } else {
    formState.checkedMenus = [];
  }
};
// 打开弹窗
const showModal = (record) => {
  if (!record) {
    modalState.title = "新增";
  } else {
    modalState.title = "修改";
    Object.assign(formState, { ...record });
  }
  // 获取系统菜单
  getAllRoutes().then((res) => {
    treeState.treeData = initTree(res.data);
  });
  modalState.visible = true;
};

// 更新角色路由
const updateRoleRoutes = () => {
  const { roles = [] } = store.state.user.userInfo;
  // 是否修改了当前登录用户的角色路由
  if (roles.includes(formState.roleKey)) {
    store.dispatch("routes/getRoutesList");
  }
};

const handleOk = () => {
  formRef.value
    .validate()
    .then(() => {
      if (modalState.title === "新增") {
        addRole(formState).then(() => {
          init();
          updateRoleRoutes();
          handleCancel();
        });
      } else {
        updateRole(formState).then(() => {
          init();
          updateRoleRoutes();
          handleCancel();
        });
      }
    })
    .catch((error) => {
      console.log("error", error);
    });
};
const handleCancel = () => {
  modalState.visible = false;
  formRef.value.resetFields();
  Object.assign(formState, getInitialData());
  Object.assign(treeState, getInitialTree());
};
</script>

<style lang="scss" scoped>
.tree-box {
  border: 1px solid #e5e6e7;
  background: #fff none;
  border-radius: 4px;
  min-height: 100px;
}
</style>
